/*
*  Network.cpp
*  SquirrelAdven
*
*  Created by Andrew Yin on 3/14/11.
*  Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#if defined(_WIN32) || defined(WIN32) 
#define OS_WIN
#endif

#ifdef OS_WIN
//Windows specific stuff
#define OS 0
#include "Network.h"
#define DEFAULT_PORT "5678"
#define DEFAULT_BUFLEN 512



//constructor
WinSockNetwork::WinSockNetwork(){
	connectToIP="localhost";

	WSADATA wsaData;
	int iResult;
	printf("WinSockNetwork Constructor\n");
	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
	}

	struct addrinfo *result = NULL,
		*ptr = NULL,
		hints;

	ZeroMemory( &hints, sizeof(hints) );
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	// Resolve the server address and port
	iResult = getaddrinfo(connectToIP, DEFAULT_PORT, &hints, &result);
	if (iResult != 0) {
		printf("getaddrinfo failed: %d\n", iResult);
		WSACleanup();
	}
	ConnectSocket = INVALID_SOCKET;


	// Attempt to connect to the first address returned by
	// the call to getaddrinfo
	ptr=result;

	// Create a SOCKET for connecting to server
	ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
		ptr->ai_protocol);

	if (ConnectSocket == INVALID_SOCKET) {
		printf("Error at socket(): %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		WSACleanup();
	}
	// Connect to server.
	iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
	if (iResult == SOCKET_ERROR) {
		closesocket(ConnectSocket);
		ConnectSocket = INVALID_SOCKET;
	}

	// Should really try the next address returned by getaddrinfo
	// if the connect call failed
	// But for this simple example we just free the resources
	// returned by getaddrinfo and print an error message

	freeaddrinfo(result);

	if (ConnectSocket == INVALID_SOCKET) {
		printf("Unable to connect to server!\n");
		WSACleanup();
	}

}

// destructor
WinSockNetwork::~WinSockNetwork() {
	int iResult;
	// shutdown the connection for sending since no more data will be sent
	// the client can still use the ConnectSocket for receiving data
	iResult = shutdown(ConnectSocket, SD_SEND);
	if (iResult == SOCKET_ERROR) {
		printf("shutdown failed: %d\n", WSAGetLastError());
		closesocket(ConnectSocket);
		WSACleanup();
	}


}

void WinSockNetwork::sendMessage(char* sendbuf){
	int iResult;

	// Send an initial buffer
	iResult = send(ConnectSocket, sendbuf, (int) strlen(sendbuf), 0);
	if (iResult == SOCKET_ERROR) {
		printf("send failed: %d\n", WSAGetLastError());
		closesocket(ConnectSocket);
		WSACleanup();
	}
	printf("Bytes Sent: %ld\n", iResult);

}
//pass in the buffer
int WinSockNetwork::receiveMessage(char *recvbuf){
	// Receive data until the server closes the connection
	int iResult;
	int recvbuflen = DEFAULT_BUFLEN;
	//do {
		iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
		//printf("len:%i\n",strlen(recvbuf));
		recvbuf[iResult]='\0';
		if (iResult > 0){
			printf("Bytes received: %d\n", iResult);
			
		}
		else if (iResult == 0)
			printf("Connection closed\n");
		else
			printf("recv failed: %d\n", WSAGetLastError());
	//} while (iResult > 0);
	return iResult;
}

#else
//Mac related stuff
#include "Network.h"
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

BSDNetwork::BSDNetwork(){

 int  numbytes;  
    char buf[MAXDATASIZE];
    struct addrinfo hints, *servinfo, *p;
    int rv;
    char s[INET6_ADDRSTRLEN];


    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if ((rv = getaddrinfo("localhost", PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        //return 1;
    }

    // loop through all the results and connect to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("client: socket");
            continue;
        }

        if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("client: connect");
            continue;
        }

        break;
    }

    if (p == NULL) {
        fprintf(stderr, "client: failed to connect\n");
    }

    inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
            s, sizeof s);
    printf("client: connecting to %s\n", s);

    freeaddrinfo(servinfo); // all done with this structure

	//fcntl(sockfd,O_NONBLOCK );//set to non blocking mode, error couldn't find this function and didn't know what O_NONBLOCK was


   /* if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
        perror("recv");
        exit(1);
    }*/
	//receiveMessage(buf);
  

    //printf("client: received '%s'\n",buf);

}

// destructor
BSDNetwork::~BSDNetwork() {
	 close(sockfd);
}
void BSDNetwork::sendMessage(char *sendbuf){
	int numbytes;
	 if ((numbytes = send(sockfd, sendbuf, (int) strlen(sendbuf), 0)) == -1) {
        perror("send");
        exit(1);
	 }
}

//pass in the buffer
int BSDNetwork::receiveMessage(char *recvbuf){
	int numbytes;
	 if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE-1, 0)) == -1) {
        perror("recv");
        exit(1);
	 }
	 printf("numbytes received:%i\n",numbytes);
	 recvbuf[numbytes] = '\0';
	 return numbytes;
	//recv(sockfd, buf, MAXDATASIZE-1, 0);
}



#endif
